<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="L97Rs" id="L97Rs"><span data-lake-id="u7bb78b3a" id="u7bb78b3a">典型回答</span></h1>
  <p data-lake-id="ue8adb7a6" id="ue8adb7a6"><br></p>
  <p data-lake-id="ue8a1eb6c" id="ue8a1eb6c"><span data-lake-id="uf12db61f" id="uf12db61f">在Java 9之前，字符串内部是由字符数组char[] 来表示的。</span></p>
  <p data-lake-id="u7352b91c" id="u7352b91c"><span data-lake-id="u1543e0fa" id="u1543e0fa">​</span><br></p>
  <pre lang="java"><code>
    /** The value is used for character storage. */
    private final char value[];
</code></pre>
  <p data-lake-id="u7f7f8872" id="u7f7f8872"><span data-lake-id="u1f98ec93" id="u1f98ec93">​</span><br></p>
  <p data-lake-id="u3a6423fd" id="u3a6423fd"><span data-lake-id="u58aeff51" id="u58aeff51">由于Java内部使用UTF-16，每个char占据两个字节，即使某些字符可以用一个字节（LATIN-1）表示，但是也仍然会占用两个字节。所以，JDK 9就对他做了优化。</span></p>
  <p data-lake-id="u8e3fb70f" id="u8e3fb70f"><span data-lake-id="uc44813f1" id="uc44813f1">​</span><br></p>
  <p data-lake-id="u7953029f" id="u7953029f"><span data-lake-id="u63fe6572" id="u63fe6572">这就是Java 9引入了"</span><strong><span data-lake-id="uf560ab7a" id="uf560ab7a">Compact String</span></strong><span data-lake-id="u9b3688ac" id="u9b3688ac">"的概念：</span></p>
  <p data-lake-id="u03b12458" id="u03b12458"><span data-lake-id="u302204ab" id="u302204ab">​</span><br></p>
  <p data-lake-id="ud5801302" id="ud5801302"><span data-lake-id="ub9111eff" id="ub9111eff">每当我们创建一个字符串时，如果它的所有字符都可以用单个字节（Latin-1）表示，那么将会在内部使用字节数组来保存一半所需的空间，但是如果有一个字符需要超过8位来表示，Java将继续使用UTF-16与字符数组。</span></p>
  <p data-lake-id="u12e7e7ab" id="u12e7e7ab"><span data-lake-id="u8b897f7e" id="u8b897f7e">​</span><br></p>
  <blockquote data-lake-id="uc6b784ba" id="uc6b784ba">
   <p data-lake-id="u91c1dcd7" id="u91c1dcd7"><span data-lake-id="uc4bb8762" id="uc4bb8762">Latin1（又称ISO 8859-1）是一种字符编码格式，用于表示西欧语言，包括英语、法语、德语、西班牙语、葡萄牙语、意大利语等。它由国际标准化组织（ISO）定义，并涵盖了包括ASCII在内的128个字符。</span></p>
   <p data-lake-id="u967a77b4" id="u967a77b4"><strong><span data-lake-id="u815d0f32" id="u815d0f32">Latin1编码使用单字节编码方案，也就是说每个字符只占用一个字节</span></strong><span data-lake-id="u228efb01" id="u228efb01">，其中第一位固定为0，后面的七位可以表示128个字符。这样，Latin1编码可以很方便地与ASCII兼容。</span></p>
  </blockquote>
  <p data-lake-id="u14f1d8de" id="u14f1d8de"><span data-lake-id="u00edb09f" id="u00edb09f">​</span><br></p>
  <p data-lake-id="u2b2b09c3" id="u2b2b09c3"><span data-lake-id="ubbc5c3d1" id="ubbc5c3d1">那么，问题来了 ，所有字符串操作时，它如何区分到底用Latin-1还是UTF-16表示呢？</span></p>
  <p data-lake-id="u7902057e" id="u7902057e"><span data-lake-id="uca5481c8" id="uca5481c8">​</span><br></p>
  <p data-lake-id="u9695d0ef" id="u9695d0ef"><span data-lake-id="u081bbaba" id="u081bbaba">为了解决这个问题，对String的内部实现进行了另一个更改。引入了一个名为coder的字段，用于保存这些信息。</span></p>
  <p data-lake-id="uc9184c8e" id="uc9184c8e"><span data-lake-id="ub29f218f" id="ub29f218f">​</span><br></p>
  <pre lang="java"><code>
/**
 * The value is used for character storage.
 *
 * @implNote This field is trusted by the VM, and is a subject to
 * constant folding if String instance is constant. Overwriting this
 * field after construction will cause problems.
 *
 * Additionally, it is marked with {@link Stable} to trust the contents
 * of the array. No other facility in JDK provides this functionality (yet).
 * {@link Stable} is safe here, because value is never null.
 */
@Stable
private final byte[] value;

/**
 * The identifier of the encoding used to encode the bytes in
 * {@code value}. The supported values in this implementation are
 *
 * LATIN1
 * UTF16
 *
 * @implNote This field is trusted by the VM, and is a subject to
 * constant folding if String instance is constant. Overwriting this
 * field after construction will cause problems.
 */
private final byte coder;
</code></pre>
  <p data-lake-id="u4fb43b2b" id="u4fb43b2b"><u><span data-lake-id="ud8ceba04" id="ud8ceba04">​</span></u><br></p>
  <p data-lake-id="ud5c19d0a" id="ud5c19d0a"><span data-lake-id="ua7abfc29" id="ua7abfc29">coder字段的取值可以是以下两种</span></p>
  <p data-lake-id="u4bbce94f" id="u4bbce94f"><span data-lake-id="u029f382a" id="u029f382a">​</span><br></p>
  <pre lang="java"><code>
static final byte LATIN1 = 0;
static final byte UTF16 = 1;
</code></pre>
  <p data-lake-id="ud005ada7" id="ud005ada7"><br></p>
  <p data-lake-id="ub9abc5b4" id="ub9abc5b4"><span data-lake-id="u5ba40da7" id="u5ba40da7">在很多字符串的相关操作中都需要做一下判断，如：</span></p>
  <p data-lake-id="u983ab3ce" id="u983ab3ce"><span data-lake-id="u49aa2541" id="u49aa2541">​</span><br></p>
  <pre lang="java"><code>
public int indexOf(int ch, int fromIndex) {
    return isLatin1() 
      ? StringLatin1.indexOf(value, ch, fromIndex) 
      : StringUTF16.indexOf(value, ch, fromIndex);
}  

private boolean isLatin1() {
    return COMPACT_STRINGS &amp;&amp; coder == LATIN1;
}
</code></pre>
 </body>
</html>